<?php
/** 
 * EGP Framework
 *
 * LICENSE
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @author     Akon(番茄红了) <aultoale@gmail.com>
 * @copyright  Copyright (c) 2008 (http://www.tblog.com.cn)
 * @license    http://www.gnu.org/licenses/gpl.html     GPL 3
 */

!defined('EGP_LIB_DIR') && die('Access Deny!');

/**
 * 提供多国语言支持
 *
 * @package    classes
 * @author     Akon(番茄红了) <aultoale@gmail.com>
 * @copyright  Copyright (c) 2008 (http://www.tblog.com.cn)
 * @license    http://www.gnu.org/licenses/gpl.html     GPL 3
 */
class EGP_Lang
{

    /**
     * 存储单件模式实例
     *
     * @var EGP_Lang
     */
    protected static $_instance = null;

    /**
     * 语言包根路径
     *
     * @var string
     */
    protected $_basePath = null;

    /**
     * 当前语言包
     *
     * @var string
     */
    protected $_lang = 'zh-cn';

    /**
     * 存储语言包数据
     *
     * @var EGP_ArrayObject
     */
    protected $_map = null;

    /**
     * 单件模式调用方法
     *
     * @return EGP_Lang
     */
    public static function getInstance()
    {
        if (!self::$_instance instanceof self)
            self::$_instance = new self();
        return self::$_instance;
    }

    /**
     * 构造方法
     *
     */
    protected function __construct()
    {
        $this->_map = new EGP_ArrayObject();
        $this->setBasePath(EGP_CFG_DIR . '/lang');
    }

    /**
     * 设定语言包根路径
     *
     * @param  string  $path
     * @return EGP_Lang
     * @throws EGP_Exception
     */
    public function setBasePath($path)
    {
         $path = EGP_Io::strip($path);
         if (!is_dir($path))
             throw new EGP_Exception("Can not found language base path: '$path'");
         $this->_basePath = $path;
         return $this;
    }

    /**
     * 获取语言包根路径
     *
     * @return string
     */
    public function getBasePath()
    {
        return $this->_basePath;
    }

    /**
     * 设定语言
     *
     * @param  string  $lang
     * @return EGP_Lang
     * @throws EGP_Exception
     */
    public function setLang($lang)
    {
        $path = $this->getBasePath();
        if (!is_dir($path . DIR_SEP . $lang))
            throw new EGP_Exception("Can not found language '$lang' in base path: '$path'");
        $this->_lang = $lang;
        $this->loadPack('core');
        return $this;
    }

    /**
     * 获取当前语言
     *
     * @return string
     */
    public function getLang()
    {
        return $this->_lang;
    }

    /**
     * 获取语言包数据文件
     *
     * @param  string  $pack
     * @param  string  $lang
     * @return string
     */
    public function getPackFile($pack, $lang = null)
    {
        empty($lang) && $lang = $this->getLang();
        return $this->getBasePath() . DIR_SEP . $lang . DIR_SEP . $pack . '.php';
    }

    /**
     * 载入语言包数据
     *
     * @param  string  $pack
     * @param  string  $lang
     * @return EGP_ArrayObject
     * @throws EGP_Exception
     */
    public function loadPack($pack, $lang = null)
    {
        empty($lang) && $lang = $this->getLang();
        if (isset($this->_map->$lang) && isset($this->_map->$lang->$pack))
            return $this->_map->$lang->$pack;
        else
            $this->_map->$lang = new EGP_ArrayObject();

        if (!$this->hasPack($pack, $lang))
            throw new EGP_Exception("Can not found package '$pack' in language: '$lang'");

        $langPath = $this->getBasePath() . DIR_SEP . $lang;
        $langPack = require($langPath . DIR_SEP . $pack . '.php');
        if (!is_array($langPack))
            throw new EGP_Exception("Invalid package '$pack' in language base path: '$langPath'");

        return $this->_map->$lang->$pack = new EGP_ArrayObject($langPack);
    }

    /**
     * 查询是否存在指定的语言包
     *
     * @param  string  $pack
     * @param  string  $lang
     * @return boolean
     */
    public function hasPack($pack, $lang = null)
    {
        empty($lang) && $lang = $this->getLang();
        return isset($this->_map->$lang->$pack) ?
            true :
            is_readable($this->getPackFile($pack, $lang));
    }

    /**
     * 获取语言包数据
     *
     * @param  string  $pack
     * @param  string  $lang
     * @return EGP_ArrayObject
     */
    public function getPack($pack = null, $lang = null)
    {
        empty($lang) && $lang = $this->getLang();
        return empty($pack) ? $this->_map->$lang : $this->loadPack($pack, $lang);
    }

    /**
     * 获取语言包类的语言数据字符串
     *
     * @param  string  $pack
     * @param  string  $name
     * @param  mixed   $args
     * @param  string  $lang
     * @return string
     */
    public function get($pack, $name, $args = null, $lang = null)
    {
        !is_array($args) && $args = array($args);
        empty($lang)     && $lang = $this->getLang();
        $pack = $this->getPack($pack, $lang);
        if (!empty($pack) && isset($pack->$name))
            return call_user_func_array('sprintf', array_merge(array($pack->$name), $args));
        return "#$name#";
    }

}